home *** CD-ROM | disk | FTP | other *** search
/ MIDICraft's MIDINET CD-ROM / MIDICraft's MIDINET CD-ROM.iso / DOSUTILS / MIDITRIM / MIDITRIM.CPP < prev    next >
Encoding:
C/C++ Source or Header  |  1997-03-10  |  7.9 KB  |  358 lines

  1. // miditrim written by Günter Nagler 1996 (gnagler@ihm.tu-graz.ac.at)
  2. #include "midiio.hpp"
  3. #include <stdlib.h>
  4. #include <string.h>
  5. #include <ctype.h>
  6. #include <assert.h>
  7.  
  8. static char* version = "miditrim v1.1 by Günter Nagler (" __DATE__ ")";
  9.  
  10. char* input = 0;
  11. char* output = 0;
  12.  
  13. int trimend = 0;
  14. int trimstart = 0;
  15.  
  16. class MidiScanStartEnd : public MidiRead
  17. {
  18. public:
  19.   MidiScanStartEnd(char* name);
  20.  
  21.   virtual void track(int trackno, long length, int channel);
  22.  
  23.   virtual void event(int what, int len = 0, unsigned char* data = 0);
  24.   virtual void noteon(int channel, int note, int vel);
  25.   virtual void noteoff(int channel, int note, int vel);
  26.   virtual void end();
  27.   virtual void meta(int what, int len, unsigned char* data);
  28.  
  29.   virtual void error(const char* msg);
  30.   virtual void warning(const char* msg);
  31.  
  32.   virtual void percent(int perc);
  33.  
  34.   long firstevent_, lastevent_;
  35.   long firstnote_, lastnote_;
  36.   long end_;
  37.  
  38. protected:
  39.   void eventtime(int noteev = 0);
  40.  
  41.   unsigned char noteplaying_[16][128];
  42. };
  43.  
  44. void MidiScanStartEnd::eventtime(int noteev)
  45. {
  46.   if (firstevent_ < 0 || getcurunit() < firstevent_)
  47.     firstevent_ =  getcurunit();
  48.   if (lastevent_ < 0 || getcurunit() > lastevent_)
  49.     lastevent_ = getcurunit();
  50.   if (noteev)
  51.   {
  52.     if (firstnote_ < 0 || getcurunit() < firstnote_)
  53.       firstnote_ =  getcurunit();
  54.     if (lastnote_ < 0 || getcurunit() > lastnote_)
  55.       lastnote_ = getcurunit();
  56.   }
  57.   if (end_ < 0 || getcurunit() > end_)
  58.     end_ = getcurunit();
  59. }
  60.  
  61. MidiScanStartEnd::MidiScanStartEnd(char* name) : MidiRead(name)
  62. {
  63.   options_ = OPTION_NOCONTROLS + OPTION_NOSYSEVENTS +
  64.          OPTION_NOPOLYEVENTS + OPTION_NOCONTROLEVENTS +
  65.          OPTION_NOPROGRAMEVENTS + OPTION_NOAFTERTOUCHEVENTS +
  66.          OPTION_NOPITCHBENDEVENTS;
  67.  
  68.   firstevent_ = -1;
  69.   lastevent_ = -1;
  70.   firstnote_ = -1;
  71.   lastnote_ = -1;
  72.   end_ = -1;
  73. }
  74.  
  75. void MidiScanStartEnd::track(int trackno, long length, int channel)
  76. {
  77.   for (int c = 0; c < 16; c++)
  78.   for (int i = 0; i < 128; i++)
  79.     noteplaying_[c][i] = 0;
  80. }
  81.  
  82. void MidiScanStartEnd::noteon(int channel, int note, int vel)
  83. {
  84.   assert(channel >= 0 && channel <= 15);
  85.   eventtime(1);
  86.   noteplaying_[channel][note] = 1;
  87. }
  88.  
  89. void MidiScanStartEnd::noteoff(int channel, int note, int vel)
  90. {
  91.   assert(channel >= 0 && channel <= 15);
  92.   if (noteplaying_[channel][note])
  93.     eventtime(1);
  94.   else
  95.     eventtime(0);  // not necessary note event
  96.   noteplaying_[channel][note] = 0;
  97. }
  98.  
  99. void MidiScanStartEnd::end() // end of track
  100. {
  101.   // not an event
  102.   if (end_ < 0 || getcurunit() > end_)
  103.     end_ = getcurunit();
  104. }
  105.  
  106. void MidiScanStartEnd::meta(int what, int len, unsigned char* data)
  107. {
  108.   eventtime();
  109. }
  110.  
  111. void MidiScanStartEnd::event(int what, int len, unsigned char* data)
  112. {
  113.   eventtime();
  114. }
  115.  
  116. void MidiScanStartEnd::percent(int perc)
  117. {
  118.     fprintf(stderr, "%-3d%%\r", perc);
  119. }
  120.  
  121. void MidiScanStartEnd::error(const char* msg)
  122. {
  123.   printf("Error: %s\n", msg);
  124.   exit(1);
  125. }
  126.  
  127. void MidiScanStartEnd::warning(const char* msg)
  128. {
  129.   printf("Warning: %s\n", msg);
  130. }
  131.  
  132.  
  133. class MidiTrim : public MidiCopy
  134. {
  135. public:
  136.   MidiTrim(char* name);
  137.  
  138.   virtual void track(int trackno, long length, int channel);
  139.  
  140.   virtual void event(int what, int len, unsigned char* data);
  141.  
  142.   virtual void time(unsigned long ticks);
  143.  
  144.   virtual void error(const char* msg);
  145.   virtual void warning(const char* msg);
  146.  
  147.  
  148.   virtual void percent(int perc);
  149.  
  150.   unsigned long trimuntil_, trimfrom_;
  151. };
  152.  
  153. MidiTrim::MidiTrim(char* name) : MidiCopy(name)
  154. {
  155.   options_ = OPTION_NOCONTROLS + OPTION_NOSYSEVENTS +
  156.          OPTION_NOPOLYEVENTS + OPTION_NOCONTROLEVENTS +
  157.          OPTION_NOPROGRAMEVENTS + OPTION_NOAFTERTOUCHEVENTS +
  158.          OPTION_NOPITCHBENDEVENTS + OPTION_NONOTEEVENTS;
  159.   trimuntil_ = 0; trimfrom_ = 0xffffffffUL;
  160. }
  161.  
  162. void MidiTrim::track(int trackno, long length, int channel)
  163. {
  164.   MidiCopy::track(trackno, length, channel);
  165. }
  166.  
  167. void MidiTrim::time(unsigned long ticks)
  168. {
  169.   long curtime = getcurunit();
  170.  
  171.   if (ticks > 0)
  172.   {
  173.     if (curtime < trimuntil_)
  174.     {
  175.       if (curtime + ticks <= trimuntil_)
  176.       {
  177.     // remove full pause
  178.     ticks = 0;
  179.     curtime += ticks;
  180.       }
  181.       else
  182.       {
  183.     // remove pause between curtime and trimuntil only
  184.     ticks =  curtime + ticks - trimuntil_;
  185.     curtime = trimuntil_;
  186.       }
  187.     }
  188.     else if (curtime + ticks >= trimfrom_)
  189.     {
  190.       if (curtime >= trimfrom_)
  191.       {
  192.     // remove full pause
  193.     ticks = 0;
  194.     curtime += ticks;
  195.       }
  196.       else
  197.       {
  198.     // keep pause till trimfrom
  199.     ticks = trimfrom_ - curunit_;
  200.     curtime = trimfrom_;
  201.       }
  202.     }
  203.   }
  204.   MidiCopy::time(ticks);
  205. }
  206.  
  207. void MidiTrim::event(int what, int len, unsigned char* data)
  208. {
  209.   MidiCopy::event(what, len, data);
  210. }
  211.  
  212. void MidiTrim::percent(int perc)
  213. {
  214.     fprintf(stderr, "%-3d%%\r", perc);
  215. }
  216.  
  217. void MidiTrim::error(const char* msg)
  218. {
  219.   printf("Error: %s\n", msg);
  220.   exit(1);
  221. }
  222.  
  223. void MidiTrim::warning(const char* msg)
  224. {
  225.   printf("Warning: %s\n", msg);
  226. }
  227.  
  228. void usage()
  229. {
  230.   printf("miditrim removes pauses at beginning and end of song\n");
  231.   printf("usage: miditrim [-start] [-end] [-both] file.mid newfile.mid\n");
  232.   printf("-version\tget program version\n");
  233.   printf("-start\t\tremove pauses before first note in song is played\n");
  234.   printf("-end\t\tremove pauses after last note in song has stopped\n");
  235.   printf("-both\t\ttrim start and end of song (is default)\n");
  236.   exit(1);
  237. }
  238.  
  239. int main(int argc, char**argv)
  240. {
  241.   argc--; argv++;
  242.   while (argc > 0 && **argv == '-')
  243.   {
  244.     if (strncmp(*argv, "-version", 2) == 0)
  245.     {
  246.       fprintf(stderr, "%s\n", version);
  247.       argc--; argv++;
  248.       if (argc == 0)
  249.     return 0;
  250.       continue;
  251.     }
  252.     if (strncmp(*argv, "-start", 2) == 0)
  253.     {
  254.       trimstart = 1;
  255.       argc--; argv++;
  256.       continue;
  257.     }
  258.     if (strncmp(*argv, "-end", 2) == 0)
  259.     {
  260.       trimend = 1;
  261.       argc--; argv++;
  262.       continue;
  263.     }
  264.     if (strncmp(*argv, "-both", 2) == 0)
  265.     {
  266.       trimstart = trimend = 1;
  267.       argc--; argv++;
  268.       continue;
  269.     }
  270.     fprintf(stderr, "invalid option %s\n", *argv);
  271.     argc--; argv++;
  272.     usage();
  273.   }
  274.   if (argc < 1)
  275.     usage();
  276.  
  277.   input = argv[0];
  278.   if (argc >= 2)
  279.   {
  280.     output = argv[1];
  281.     if (strcmp(input, output) == 0)
  282.     {
  283.       fprintf(stderr, "cannot convert midi to same file\n");
  284.       return 1;
  285.     }
  286.   }
  287.  
  288.   if (!trimstart && !trimend)
  289.     trimstart = trimend = 1;  // default: trimboth
  290.  
  291.   MidiScanStartEnd midi(input);
  292.   if (!midi.getf())
  293.   {
  294.     perror(input);
  295.     return 1;
  296.   }
  297.   midi.run();
  298.  
  299.   if (argc == 1)
  300.   {
  301.     printf("File: %s\n", input);
  302.     printf("first event: %ld\n", midi.firstevent_);
  303.     printf("last event: %ld\n", midi.lastevent_);
  304.     printf("first note: %ld\n", midi.firstnote_);
  305.     printf("last note: %ld\n", midi.lastnote_);
  306.     printf("end: %ld\n", midi.end_);
  307.     if (midi.firstnote_ > 0)
  308.       printf("pause 0-%ld could be trimmed.\n", midi.firstnote_);
  309.     if (midi.lastnote_ < midi.end_)
  310.       printf("pause %ld-%ld could be trimmed.\n", midi.lastnote_, midi.end_);
  311.   }
  312.  
  313.   if (midi.firstnote_ == 0 && midi.lastnote_ == midi.end_)
  314.   {
  315.     printf("%s is already trimmed.\n", input);
  316.   }
  317.  
  318.   if (argc == 1)
  319.     return 0;
  320.   MidiTrim midicopy(input);
  321.   if (!midi.getf())
  322.   {
  323.     perror(input);
  324.     return 1;
  325.   }
  326.  
  327.   MidiWrite* write = new MidiWrite(output);
  328.   if (!write)
  329.   {
  330.     fprintf(stderr, "out of memory\n");
  331.     return 1;
  332.   }
  333.   if (!write->getf())
  334.   {
  335.     perror(output);
  336.     return 1;
  337.   }
  338.   argc--; argv++;
  339.  
  340.   midicopy.setoutput(write);
  341.  
  342.   if (trimstart)
  343.     midicopy.trimuntil_ = midi.firstnote_;
  344.   else
  345.     midicopy.trimuntil_ = 0;
  346.  
  347.   if (trimend)
  348.     midicopy.trimfrom_ = midi.lastnote_;
  349.   else
  350.     midicopy.trimfrom_ = midi.lastevent_;
  351.   if (!midicopy.run())
  352.     fprintf(stderr, "%s: midi read error at %04lX\n", input, midi.getpos());
  353.   else
  354.     printf("output written to %s\n", output);
  355.   delete write;
  356.   return 0;
  357. }
  358.